Rem
	NOTES:
	---Endianness---
	The whole engine (game and editor) use the Little Endian byte format.
	Use the LittleEndianStream command in every binary file stream instance.
	Text files that only use readline should be okay to use regular streams, but
	it is recommended to use LittleEndianStream anyways for good practice (and in
	case another developer comes on that doesn't read this!)
End Rem

Import MaxGUI.Drivers

Const PROG_VERSION:Short = 1

Include "LQProject.bmx"
Include "LQZone.bmx"
Include "LQScript.bmx"

AppTitle = "LQuest Unified Editor"
Global ProjectFolder:String = "Projects/TestProject"

'DON'T INIT HERE. INIT BELOW (after the elements are initialized)
Global GetTextCallback(str:String)
Global GetAssetCallback(str:String)

Global	FrmGetText:TGadget
Global	GetTextCancel:TGadget
Global	GetTextOK:TGadget
Global	GetTextText:TGadget
Global	GetTextDescription:TGadget
Global	MainTabber:TGadget
Global	ZoneCbbSelector:TGadget
Global	ZoneCbbStartScriptFile:TGadget
Global	ZoneCbbStartScriptFunc:TGadget
Global	Label2:TGadget
Global	ZoneBtnNew:TGadget
Global	ZoneBtnSave:TGadget
Global	PublishSettingsGroup:TGadget
Global	Label1:TGadget
Global	TxtProjectName:TGadget
Global	PublishBtn:TGadget
Global	BtnSaveScript:TGadget
Global	TxtScript:TGadget
Global	BtnOpenScript:TGadget
Global	BtnNewScript:TGadget
Global	PublishBtnSettingsSave:TGadget
Global	CurrentScriptFile:TGadget
Global	FrmGetAsset:TGadget
Global	GetAssetCancel:TGadget
Global	GetAssetOK:TGadget
Global	GetAssetDescription:TGadget
Global	GetAssetList:TGadget

FrmGetText = CreateWindow("FrmGetText...",16,615,245,123,Null,WINDOW_TITLEBAR|WINDOW_TOOL |WINDOW_HIDDEN |WINDOW_CENTER)
	GetTextCancel = CreateButton("Cancel",5,69,75,25,FrmGetText,BUTTON_PUSH)
	GetTextOK = CreateButton("OK",148,69,86,25,FrmGetText,BUTTON_PUSH)
	GetTextText = CreateTextField(5,35,229,22,FrmGetText,Null)
	GetTextDescription = CreateLabel("GetTextDescription...",5,11,229,18,FrmGetText,Null)
FrmGetAsset = CreateWindow("FrmGetAsset...",16,615,245,323,Null,WINDOW_TITLEBAR|WINDOW_TOOL|WINDOW_HIDDEN|WINDOW_CENTER)
	GetAssetCancel = CreateButton("Cancel",5,269,75,25,FrmGetAsset,BUTTON_PUSH)
	GetAssetOK = CreateButton("OK",148,269,86,25,FrmGetAsset,BUTTON_PUSH)
	GetAssetDescription = CreateLabel("GetAssetDescription...",5,11,229,18,FrmGetAsset,Null)
	GetAssetList = CreateListBox(5,35,229,222,FrmGetAsset,Null)
Global FrmMain:TGadget = CreateWindow("LQuest Unified Editor",340,72,1024,768,Null,WINDOW_TITLEBAR|WINDOW_CENTER)
	ActivateWindow( FrmMain )
	MainTabber = CreateTabber(-1,-1,1021,740,FrmMain,Null)
		AddGadgetItem( MainTabber,"Publish",GADGETITEM_DEFAULT )
		Local MainTabber_Tab1:TGadget = CreatePanel( 0,0,ClientWidth(MainTabber),ClientHeight(MainTabber),MainTabber )
			MainTabber.items[0].extra = MainTabber_Tab1
			SetGadgetLayout( MainTabber_Tab1,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED )
			PublishSettingsGroup = CreatePanel(391,8,273,77,MainTabber_Tab1,PANEL_GROUP,"Publishing Settings")
				Label1 = CreateLabel("Game Title",4,6,80,14,PublishSettingsGroup,Null)
				TxtProjectName = CreateTextField(4,30,250,18,PublishSettingsGroup,Null)
					SetGadgetText( TxtProjectName,"")
			PublishBtn = CreateButton("Publish",912,688,100,25,MainTabber_Tab1,BUTTON_PUSH)
			PublishBtnSettingsSave = CreateButton("Save",487,105,75,23,MainTabber_Tab1,BUTTON_PUSH)
		AddGadgetItem( MainTabber,"Scripts",GADGETITEM_NORMAL )
		Local MainTabber_Tab2:TGadget = CreatePanel( 0,0,ClientWidth(MainTabber),ClientHeight(MainTabber),MainTabber )
			MainTabber.items[1].extra = MainTabber_Tab2
			SetGadgetLayout( MainTabber_Tab2,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED )
			BtnSaveScript = CreateButton("Save Current Script",253,7,130,25,MainTabber_Tab2,BUTTON_PUSH)
			TxtScript = CreateTextArea(2,45,1011,666,MainTabber_Tab2)
			BtnOpenScript = CreateButton("Open Script...",115,7,118,25,MainTabber_Tab2,BUTTON_PUSH)
			BtnNewScript = CreateButton("New Script...",7,7,88,25,MainTabber_Tab2,BUTTON_PUSH)
			CurrentScriptFile = CreateLabel("No Script Open",403,10,130,22,MainTabber_Tab2,Null)
		AddGadgetItem( MainTabber,"Zones",GADGETITEM_NORMAL )
		Local MainTabber_Tab3:TGadget = CreatePanel( 0,0,ClientWidth(MainTabber),ClientHeight(MainTabber),MainTabber )
			MainTabber.items[2].extra = MainTabber_Tab3
			SetGadgetLayout( MainTabber_Tab3,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED )
			ZoneCbbSelector = CreateComboBox(3,4,162,25,MainTabber_Tab3,Null)
			ZoneCbbStartScriptFile = CreateComboBox(450,4,249,25,MainTabber_Tab3,Null)
			AddGadgetItem(ZoneCbbStartScriptFile,"None")
			Label2 = CreateLabel("Start Script",374,10,68,14,MainTabber_Tab3,Null)
			ZoneBtnNew = CreateButton("New Zone...",177,4,75,25,MainTabber_Tab3,BUTTON_PUSH)
			ZoneBtnSave = CreateButton("Save Zone",267,4,75,25,MainTabber_Tab3,BUTTON_PUSH)
			ZoneCbbStartScriptFunc = CreateComboBox(719,4,291,25,MainTabber_Tab3,Null)
			AddGadgetItem(ZoneCbbStartScriptFunc,"None")
		AddGadgetItem( MainTabber,"!Testing!",GADGETITEM_NORMAL )
		Local MainTabber_Tab4:TGadget = CreatePanel( 0,0,ClientWidth(MainTabber),ClientHeight(MainTabber),MainTabber )
			MainTabber.items[3].extra = MainTabber_Tab4
			SetGadgetLayout( MainTabber_Tab4,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED )
		MainTabber_GA( MainTabber , 0 )

'INIT GOES HERE!
LQProject.Init(ProjectFolder + "/project.dat")
LQScript.Init()
LQZone.Init()


Repeat
	WaitEvent()
	Select EventID()
		Case EVENT_WINDOWCLOSE
			Select EventSource()
				Case FrmGetText	FrmGetText_WC( FrmGetText )
				Case FrmMain	FrmMain_WC( FrmMain )
				Case FrmGetAsset	FrmGetAsset_WC( FrmGetAsset )
			End Select

		Case EVENT_GADGETACTION
			Select EventSource()
				Case GetTextCancel	GetTextCancel_GA( GetTextCancel )
				Case GetTextOK	GetTextOK_GA( GetTextOK )
				Case GetAssetCancel	GetAssetCancel_GA( GetAssetCancel )
				Case GetAssetOK	GetAssetOK_GA( GetAssetOK )
				Case MainTabber	MainTabber_GA( MainTabber , EventData() )
				Case ZoneCbbSelector	ZoneCbbSelector_GA( ZoneCbbSelector , EventData() )
				Case ZoneCbbStartScriptFile	ZoneCbbStartScriptFile_GA( ZoneCbbStartScriptFile , EventData() )
				Case ZoneCbbStartScriptFunc ZoneCbbStartScriptFunc_GA( ZoneCbbStartScriptFunc , EventData() )
				Case ZoneBtnNew	ZoneBtnNew_GA( ZoneBtnNew )
				Case ZoneBtnSave	ZoneBtnSave_GA( ZoneBtnSave )
				Case TxtProjectName	TxtProjectName_GA( TxtProjectName )
				Case PublishBtn	PublishBtn_GA( PublishBtn )
				Case BtnSaveScript	BtnSaveScript_GA( BtnSaveScript )
				Case TxtScript	TxtScript_GA( TxtScript )
				Case BtnOpenScript	BtnOpenScript_GA( BtnOpenScript )
				Case BtnNewScript	BtnNewScript_GA( BtnNewScript )
				Case PublishBtnSettingsSave	PublishBtnSettingsSave_GA(PublishBtnSettingsSave)
			End Select

	End Select
Forever

Function FrmGetText_WC( Window:TGadget )
	GetTextCancel_GA(GetTextCancel)
End Function

Function FrmGetAsset_WC(Window:TGadget)
	GetAssetCancel_GA(GetAssetCancel)
End Function

Function FrmMain_WC( Window:TGadget )
	If Proceed("Are you sure you want to quit? All unsaved progress will be lost!",True) = 1 Then
		End
	EndIf
End Function

Function GetTextCancel_GA( Button:TGadget )
	'call callback with the text entered. in this case, ""
	GetTextCallback("")
	'allow access to frmmain, and hide frmgettext...
	HideGadget(FrmGetText)
	EnableGadget(FrmMain)
	ActivateGadget(FrmMain)
End Function

Function GetAssetCancel_GA(Button:TGadget)
	'call callback with the text entered, or in this case, ""
	GetAssetCallback("")
	'allow access to frmmain, and hide frmgetasset
	HideGadget(FrmGetAsset)
	EnableGadget(FrmMain)
	ActivateGadget(FrmMain)
End Function

Function GetTextOK_GA( Button:TGadget )
	GetTextCallback(GadgetText(GetTextText))
	HideGadget(FrmGetText)
	EnableGadget(FrmMain)
	ActivateGadget(FrmMain)
End Function

Function GetAssetOK_GA(Button:TGadget)
	GetAssetCallback(GadgetItemText(GetAssetList,SelectedGadgetItem(GetAssetList)))
	HideGadget(FrmGetAsset)
	EnableGadget(FrmMain)
	ActivateGadget(FrmMain)
End Function

Function MainTabber_GA( Tabber:TGadget , Number:Int )
	For Local i:Int = 0 To Tabber.items.length -1
		HideGadget( TGadget( Tabber.items[i].extra ) )
	Next
	ShowGadget( TGadget( Tabber.items[Number].extra ) )
	
End Function

Function ZoneCbbSelector_GA( Combo:TGadget , Number:Int )
	'update the zone script list [with the selected zone's script filename and function]...
	Local zone:LQZone = LQZone(GadgetItemExtra(Combo,Number))
	If zone.startScriptFile = "" Then
		List_SelectWhere(ZoneCbbStartScriptFile,"None")
		List_ClearToNone(ZoneCbbStartScriptFunc)
		Return
	EndIf
	List_SelectWhere(ZoneCbbStartScriptFile,zone.startScriptFile)
	List_ScriptFunctions(ZoneCbbStartScriptFunc,zone.startScriptFile)
End Function

Function ZoneCbbStartScriptFile_GA( Combo:TGadget , Number:Int )
	If GadgetItemText(Combo,Number) = "None" Then
		List_ClearToNone(ZoneCbbStartScriptFunc)
		Return
	EndIf
	If Not List_ScriptFunctions(ZoneCbbStartScriptFunc,GadgetItemText(Combo,Number)) Then
		Notify("No Functions Found In Lua File ~q" + GadgetItemText(Combo,Number) + ".lua~q",False)
		Local noneIndex:Int = List_SelectWhere(Combo,"None")
		If noneIndex = -1 Then
			Error("ZoneCbbStartScriptFile Combobox Gadget Action Handler Error. Requires Debugging!")
		EndIf
		ZoneCbbStartScriptFile_GA(Combo,noneIndex)
	EndIf
End Function

Function ZoneCbbStartScriptFunc_GA( Combo:TGadget , Number:Int )
	'nothing to do here...
End Function

Function ZoneBtnNew_GA( Button:TGadget )
	GetTextInput("New Zone...","New Zone Name:",NewZoneNameReceived)
End Function

Function PublishBtnSettingsSave_GA(Button:TGadget)
	LQProject.Save(ProjectFolder + "/project.dat")
End Function

Function ZoneBtnSave_GA( Button:TGadget )
	If SelectedGadgetItem(ZoneCbbSelector) = -1 Then
		Notify("Can't Save Zone: No Zone Selected!")
		Return
	EndIf
	Local zone:LQZone = LQZone(GadgetItemExtra(ZoneCbbSelector,SelectedGadgetItem(ZoneCbbSelector)))
	zone.Save(ProjectFolder + "/Data/Zones/" + zone.name + ".dat")
End Function

Function TxtProjectName_GA( TextField:TGadget )
	
End Function

Function PublishBtn_GA( Button:TGadget )
	
End Function

Function BtnSaveScript_GA( Button:TGadget )
	Local script:LQScript = LQScript(GadgetExtra(CurrentScriptFile))
	If script = Null Then Return
	script.SaveFromBox()
End Function

Function TxtScript_GA( TextField:TGadget )
	
End Function

Function BtnOpenScript_GA( Button:TGadget )
	If Proceed("Are you sure you want to close the script? All unsaved progess on the script will be lost!",True) <> 1 Then Return
	GetAssetInput("Open Script...","Pick a script to edit:",ProjectFolder + "/Assets/Scripts","lua",OpenScriptNameReceived)
End Function

Function OpenScriptNameReceived(text:String)
	If text = "" Then Return
	Local script:LQScript = LQScript.GetScriptByFileName(text)
	If script = Null Then
		script = New LQScript.Create(text)
	EndIf
	SetGadgetText(CurrentScriptFile,text)
	SetGadgetExtra(CurrentScriptFile,script)
	script.LoadIntoBox()
End Function

Function BtnNewScript_GA( Button:TGadget )
	If Proceed("Are you sure you want to close the script? All unsaved progess on the script will be lost!",True) <> 1 Then Return
	GetTextInput("New Script...","Enter the new script's name:",NewScriptNameReceived)
End Function

Function NewScriptNameReceived(text:String)
	If text = "" Then Return
	If FileType(ProjectFolder + "/Assets/Scripts/" + StripAll(text) + ".lua") = 1 Then
		Notify "A Script Named ~q" + StripAll(text) + "~q Already Exists!"
		Return
	EndIf
	Local script:LQScript = New LQScript.Create(StripAll(text))
	SetGadgetText(CurrentScriptFile,text)
	SetGadgetExtra(CurrentScriptFile,script)
	SetTextAreaText(TxtScript,"")
End Function

Function List_ScriptFunctions:Int(list:TGadget,scriptFile:String)
	Local functions:TList = LQScript.GetFunctions(scriptFile)
	'clear the script functions list and add this script's functions in...
	ClearGadgetItems(list)
	If CountList(functions) < 1 Then
		List_ClearToNone(list)
		Return False
	EndIf
	For Local func:String = EachIn functions
		AddGadgetItem(list,func)
	Next
	Return True
End Function

Function List_ClearToNone(list:TGadget)
	ClearGadgetItems(list)
	AddGadgetItem(list,"None")
	SelectGadgetItem(list,0)
End Function

Function List_SelectWhere:Int(list:TGadget,name:String="None")
	For Local i:Int = 0 Until CountGadgetItems(list)
		If GadgetItemText(list,i) = name Then
			SelectGadgetItem(list,i)
			Return i
		EndIf
	Next
	Return -1
End Function

Function NewZoneNameReceived(text:String)
	If text = "" Then Return
	If FileType(ProjectFolder + "/Data/Zones/" + StripDir(text) + ".dat") = 1 Then
		Notify("A Zone Names ~q" + text + "~q Already Exists In The Current Project!")
		Return
	EndIf
	'create the new zone...
	Local newZone:LQZone = New LQZone.Create(text)
	'add the zone into the zones list...
	AddGadgetItem(ZoneCbbSelector,text,0,-1,"",newZone)
	Local addedItem:Int = CountGadgetItems(ZoneCbbSelector)-1
	If addedItem > 0 Then
		SelectGadgetItem(ZoneCbbSelector,addedItem)
		ZoneCbbSelector_GA(ZoneCbbSelector,addedItem)
	EndIf
End Function


Function GetTextInput(title:String,message:String,callback(text:String))
	GetTextCallback = callback
	SetGadgetText(FrmGetText,title)
	SetGadgetText(GetTextDescription,message)
	DisableGadget(FrmMain)
	ShowGadget(FrmGetText)
End Function

Function GetAssetInput(title:String,message:String,folder:String,extension:String,callback(text:String))
	If FileType(folder) <> 2 Then
		Error("Invalid Asset Input Search Folder: ~q" + folder + "~q")
	EndIf
	GetAssetCallback = callback
	SetGadgetText(FrmGetAsset,title)
	SetGadgetText(GetAssetDescription,message)
	DisableGadget(FrmMain)
	'clear and repopulate the listbox...
	ClearGadgetItems(GetAssetList)
	Local dir = ReadDir(folder)
		Repeat
			Local file:String = NextFile(dir)
			If file = "" Then Exit
			If file = "." Or file = ".." Then Continue
			If ExtractExt(file) = extension Then
				AddGadgetItem(GetAssetList,StripExt(file))
			EndIf
		Forever
	CloseDir dir
	ShowGadget(FrmGetAsset)
End Function

Function Error(errorMsg:String="Unknown Error")
?Debug
	RuntimeError("There's a problem (report it on the forums IF SOMEONE HASN'T ALREADY): ~q" + errorMsg + "~q")
?Not Debug
	Notify("There's a problem (report it on the forums IF SOMEONE HASN'T ALREADY): ~q" + errorMsg + "~q",True)
	End
?
End Function